package cn.org.donald.framework.authentication.filter;

import com.auth0.jwt.exceptions.*;
import cn.org.donald.framework.pojo.dto.JWTToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
 * @author ： Donald
 * @date ： 2020/10/18 23:09
 * @description：
 */
public class JwtFilter extends AccessControlFilter {

    private Logger logger = LoggerFactory.getLogger(JwtFilter.class);

    /**
     * 返回true直接放行
     * @param servletRequest
     * @param servletResponse
     * @param o
     * @return
     * @throws Exception
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
        Subject subject = SecurityUtils.getSubject();
        //当主体不为null,且认证通过时放行
        return subject != null && subject.isAuthenticated();
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("authorization");

        //如果客户端没携带token
        if (StringUtils.isEmpty(token)){
            logger.info("请求头没有携带token直接放行");
            return true;
        }
        JWTToken jwtToken = new JWTToken(token);
        Subject subject = SecurityUtils.getSubject();

        try {

            subject.login(jwtToken);

        } catch (AlgorithmMismatchException exception) {
            exception.printStackTrace();
            throw new AuthenticationException("算法不匹配异常");
        } catch (SignatureVerificationException exception) {
            exception.printStackTrace();
            throw new AuthenticationException("签名验证异常");
        } catch (TokenExpiredException exception) {
            exception.printStackTrace();
            throw new AuthenticationException("token过期异常");
        } catch (InvalidClaimException exception) {
            exception.printStackTrace();
            throw new AuthenticationException("无效Claim异常");
        } catch (JWTDecodeException exception) {
            exception.printStackTrace();
            throw new AuthenticationException("JWT解码异常");
        } catch (JWTVerificationException exception) {
            exception.printStackTrace();
            throw new AuthenticationException("JWT验证异常");
        } catch (UnauthorizedException e){
            throw new UnknownAccountException("权限不足");
        }
        return true;
    }
}
